home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / src890906.arc / SOCKET.C < prev    next >
C/C++ Source or Header  |  1989-09-07  |  47KB  |  1,972 lines

  1. #include <stdio.h>
  2. #ifdef    __STDC__
  3. #include <stdarg.h>
  4. #endif
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "netuser.h"
  8. #include "timer.h"
  9. #include "iface.h"
  10. #include "ip.h"
  11. #include "tcp.h"
  12. #include "udp.h"
  13. #include "ax25.h"
  14. #include "lapb.h"
  15. #include "netrom.h"
  16. #include "nr4.h"
  17. #include "proc.h"
  18. #include "usock.h"
  19. #include "socket.h"
  20. #include "config.h"
  21.  
  22. extern int errno;
  23.  
  24. static void autobind __ARGS((int s,int af));
  25. static int checkaddr __ARGS((int type,char *name,int namelen));
  26. static struct usock *itop __ARGS((int s));
  27. static void rip_recv __ARGS((struct raw_ip *rp));
  28. static void s_nrcall __ARGS((struct nr4cb *cb,int cnt));
  29. static void s_nscall __ARGS((struct nr4cb *cb,int old,int new));
  30. static void s_ntcall __ARGS((struct nr4cb *cb,int cnt));
  31. static void s_trcall __ARGS((struct tcb *tcb,int cnt));
  32. static void s_tscall __ARGS((struct tcb *tcb,int old,int new));
  33. static void s_ttcall __ARGS((struct tcb *tcb,int cnt));
  34. static void s_urcall __ARGS((struct iface *iface,struct udp_cb *udp,int cnt));
  35. static void trdiscard __ARGS((struct tcb *tcb,int cnt));
  36.  
  37. static int16 Lport = 1024;
  38.  
  39. char *Socktypes[] = {
  40.     "Not Used",
  41.     "TCP",
  42.     "UDP",
  43.     "AX25 I",
  44.     "AX25 UI",
  45.     "Raw IP",
  46.     "NETROM3",
  47.     "NETROM"
  48. };
  49. static char  Badsocket[] = "Bad socket";
  50. struct usock *Usock;        /* Socket entry array */
  51. int Nusock = DEFNSOCK;        /* Number of socket entries */
  52.  
  53. /* The following two variables are needed because there can be only one
  54.  * socket listening on each of the AX.25 modes (I and UI)
  55.  */
  56. #ifdef    AX25
  57. int Axi_sock = -1;    /* Socket number listening for AX25 connections */
  58. static int Axui_sock = -1;    /* Socket number listening for AX25 UI frames */
  59. static struct mbuf *Bcq;    /* Queue of incoming UI frames */
  60.  
  61. /* Function that handles incoming UI frames from lapb.c */
  62. void
  63. beac_input(iface,src,bp)
  64. struct iface *iface;
  65. struct ax25_addr *src;
  66. struct mbuf *bp;
  67. {
  68.     struct mbuf *hdr;
  69.     struct sockaddr_ax *sax;
  70.  
  71.     if(Axui_sock == -1){
  72.         /* Nobody there to read it */
  73.         free_p(bp);
  74.     } else {
  75.         if((hdr = pushdown(NULLBUF,sizeof(struct sockaddr_ax))) == NULLBUF){
  76.             free_p(bp);
  77.             return;
  78.         }
  79.         sax = (struct sockaddr_ax *)hdr->data;
  80.         sax->sax_family = AF_AX25;
  81.         ASSIGN(sax->ax25_addr,*src);
  82.         strncpy((char *)sax->iface,iface->name,ILEN);
  83.         hdr->next = bp;
  84.         enqueue(&Bcq,hdr);
  85.     }
  86. }
  87. #endif
  88.  
  89. /* Initialize user socket array */
  90. void
  91. sockinit()
  92. {
  93.     if(Usock != NULLUSOCK)
  94.         return;    /* Already initialized */
  95.     Usock = (struct usock *)calloc(Nusock,sizeof(struct usock));
  96. }
  97.  
  98. /* Create a user socket, return socket index
  99.  * The mapping to actual protocols is as follows:
  100.  *        
  101.  *        
  102.  * ADDRESS FAMILY    Stream        Datagram    Raw        Seq. Packet
  103.  *
  104.  * AF_INET        TCP        UDP        IP
  105.  * AF_AX25        I-frames    UI-frames
  106.  * AF_NETROM                        NET/ROM L3  NET/ROM L4
  107.  */
  108. int
  109. socket(af,type,protocol)
  110. int af;        /* Address family */
  111. int type;    /* Stream or datagram */
  112. int protocol;    /* Used for raw IP sockets */
  113. {
  114.     register struct usock *up;
  115.     int s;
  116.  
  117.     for(up=Usock;up < &Usock[Nusock];up++)
  118.         if(up->type == NOTUSED)
  119.             break;
  120.  
  121.     if(up == &Usock[Nusock]){
  122.         /* None left */
  123.         errno = EMFILE;
  124.         return -1;
  125.     }
  126.     s = up - Usock;
  127.     errno = 0;
  128.     up->noblock = 0;
  129.     up->rdysock = -1;
  130.     up->cb.p = NULLCHAR;
  131.     up->peername = up->name = NULLCHAR;
  132.     up->namelen = up->peernamelen = 0;
  133.     up->owner = Curproc;
  134.     memset(up->errcodes,0,sizeof(up->errcodes));
  135.     switch(af){
  136. #ifdef    AX25
  137.     case AF_AX25:
  138.         switch(type){
  139.         case SOCK_STREAM:
  140.             up->type = TYPE_AX25I;
  141.             break;
  142.         case SOCK_DGRAM:
  143.             up->type = TYPE_AX25UI;
  144.             break;
  145.         default:
  146.             errno = ESOCKTNOSUPPORT;
  147.             break;
  148.         }
  149.         break;
  150. #endif
  151. #ifdef NETROM
  152.     case AF_NETROM:
  153.         switch(type){
  154.         case SOCK_RAW:
  155.             up->type = TYPE_NETROML3;
  156.             up->cb.rnr = raw_nr(protocol);
  157.             break;
  158.         case SOCK_SEQPACKET:
  159.             up->type = TYPE_NETROML4;
  160.             break;
  161.         default:
  162.             errno = ESOCKTNOSUPPORT;
  163.             break;
  164.         }
  165.         break;
  166. #endif
  167.     case AF_INET:
  168.         switch(type){
  169.         case SOCK_STREAM:
  170.             up->type = TYPE_TCP;
  171.             break;
  172.         case SOCK_DGRAM:
  173.             up->type = TYPE_UDP;
  174.             break;
  175.         case SOCK_RAW:
  176.             up->type = TYPE_RAW;
  177.             up->cb.rip = raw_ip(protocol,rip_recv);
  178.                         up->cb.rip->user = s;
  179.             break;
  180.         default:
  181.             errno = ESOCKTNOSUPPORT;
  182.             break;
  183.         }
  184.         break;
  185.     default:
  186.         errno = EAFNOSUPPORT;
  187.         break;
  188.     }
  189.     if(errno)
  190.         return -1;
  191.  
  192.     return s;
  193. }
  194.  
  195. /* Attach a local address/port to a socket. If not issued before a connect
  196.  * or listen, will be issued automatically
  197.  */
  198. int
  199. bind(s,name,namelen)
  200. int s;        /* Socket index */
  201. char *name;    /* Local name */
  202. int namelen;    /* Length of name */
  203. {
  204.     register struct usock *up;
  205.     union sp local;
  206.     struct socket lsock;
  207.  
  208.     if((up = itop(s)) == NULLUSOCK){
  209.         errno = EBADF;
  210.         return -1;
  211.     }
  212.     if(name == NULLCHAR){
  213.         errno = EFAULT;
  214.         return -1;
  215.     }
  216.     if(up->name != NULLCHAR){
  217.         /* Bind has already been issued */
  218.         errno = EINVAL;
  219.         return -1;
  220.     }
  221.     if(checkaddr(up->type,name,namelen) == -1){
  222.         /* Incorrect length or family for chosen protocol */
  223.         errno = EAFNOSUPP;
  224.         return -1;    
  225.     }
  226.     /* Stash name in an allocated block */
  227.     up->namelen = namelen;
  228.     up->name = malloc(namelen);
  229.     memcpy(up->name,name,namelen);
  230.     /* Create control block for datagram sockets */
  231.     switch(up->type){
  232.     case TYPE_UDP:
  233.         local.in = (struct sockaddr_in *)up->name;
  234.         lsock.address = local.in->sin_addr.s_addr;
  235.         lsock.port = local.in->sin_port;
  236.         up->cb.udp = open_udp(&lsock,s_urcall);
  237.         up->cb.udp->user = s;
  238.         break;
  239. #ifdef    AX25
  240.     case TYPE_AX25UI:
  241.         if(Axui_sock != -1){
  242.             errno = EADDRINUSE;
  243.             return -1;
  244.         }
  245.         Axui_sock = s;
  246.         break;
  247. #endif
  248.     }
  249.     return 0;
  250. }
  251. /* Post a listen on a socket */
  252. int
  253. listen(s,backlog)
  254. int s;        /* Socket index */
  255. int backlog;    /* 0 for a single connection, 1 for multiple connections */
  256. {
  257.     register struct usock *up;
  258.     union sp local;
  259.     struct socket lsock;
  260.  
  261.     if((up = itop(s)) == NULLUSOCK){
  262.         errno = EBADF;
  263.         return -1;
  264.     }
  265.     if(up->cb.p != NULLCHAR){
  266.         errno = EISCONN;
  267.         return -1;
  268.     }
  269.     switch(up->type){
  270.     case TYPE_TCP:
  271.         if(up->name == NULLCHAR)
  272.             autobind(s,AF_INET);
  273.  
  274.         local.in = (struct sockaddr_in *)up->name;
  275.         lsock.address = local.in->sin_addr.s_addr;
  276.         lsock.port = local.in->sin_port;
  277.         up->cb.tcb = open_tcp(&lsock,NULLSOCK,
  278.          backlog ? TCP_SERVER:TCP_PASSIVE,0,
  279.         s_trcall,s_ttcall,s_tscall,0,s);
  280.         break;
  281. #ifdef AX25
  282.     case TYPE_AX25I:
  283.         if(up->name == NULLCHAR)
  284.             autobind(s,AF_AX25);
  285.         if(s != Axi_sock){
  286.             errno = EOPNOTSUPP;
  287.             return -1;
  288.         }
  289.         local.ax = (struct sockaddr_ax *)up->name;
  290.         up->cb.ax25 = open_ax25(NULLIF,&local.ax->ax25_addr,NULLAXADDR,
  291.         backlog ? AX_SERVER:AX_PASSIVE,0,
  292.         s_arcall,s_atcall,s_ascall,s);
  293.         break;
  294. #endif
  295. #ifdef NETROM
  296.     case TYPE_NETROML4:
  297.         if(up->name == NULLCHAR)
  298.             autobind(s,AF_NETROM);
  299.         local.nr = (struct sockaddr_nr *)up->name;
  300.         up->cb.nr4 = open_nr4(&local.nr->nr_addr,NULLNRADDR,
  301.         backlog ? AX_SERVER:AX_PASSIVE,
  302.         s_nrcall,s_ntcall,s_nscall,s);
  303.         break;
  304. #endif
  305.     default:
  306.         /* Listen not supported on datagram sockets */
  307.         errno = EOPNOTSUPP;
  308.         return -1;        
  309.     }
  310.     return 0;
  311. }
  312. /* Initiate active open. For datagram sockets, merely bind the remote address. */
  313. int
  314. connect(s,peername,peernamelen)
  315. int s;            /* Socket index */
  316. char *peername;        /* Peer name */
  317. int peernamelen;    /* Length of peer name */
  318. {
  319.     register struct usock *up;
  320.     union cb cb;
  321.     union sp local,remote;
  322.     struct socket lsock,fsock;
  323. #ifdef    AX25
  324.     struct iface *iface;
  325. #endif
  326.  
  327.     if((up = itop(s)) == NULLUSOCK){
  328.         errno = EBADF;
  329.         return -1;
  330.     }
  331.     if(peername == NULLCHAR){
  332.         /* Connect must specify a remote address */
  333.         errno = EFAULT;
  334.         return -1;
  335.     }
  336.     if(checkaddr(up->type,peername,peernamelen) == -1){
  337.         errno = EAFNOSUPPORT;
  338.         return -1;
  339.     }
  340.     /* Raw socket control blocks are created in socket() */
  341.     if(up->type != TYPE_RAW && up->type != TYPE_NETROML3 &&
  342.        up->cb.p != NULLCHAR){
  343.         errno = EISCONN;
  344.         return -1;
  345.     }
  346.     if((up->peername = malloc(peernamelen)) == NULLCHAR){
  347.         errno = ENOMEM;
  348.         return -1;
  349.     }
  350.     memcpy(up->peername,peername,peernamelen);
  351.     up->peernamelen = peernamelen;
  352.  
  353.     /* Set up the local socket structures */
  354.     if(up->name == NULLCHAR){
  355.         switch(up->type){
  356.         case TYPE_TCP:
  357.         case TYPE_UDP:
  358.         case TYPE_RAW:
  359.             autobind(s,AF_INET);
  360.             break;
  361.         case TYPE_AX25I:
  362.         case TYPE_AX25UI:
  363.             autobind(s,AF_AX25);
  364.             break;
  365.         case TYPE_NETROML3:
  366.         case TYPE_NETROML4:
  367.             autobind(s,AF_NETROM);
  368.             break;
  369.         }
  370.     }
  371.     switch(up->type){
  372.     case TYPE_TCP:
  373.         /* Construct the TCP-style ports from the sockaddr structs */
  374.         local.in = (struct sockaddr_in *)up->name;
  375.         lsock.address = local.in->sin_addr.s_addr;
  376.         lsock.port = local.in->sin_port;
  377.  
  378.         remote.in = (struct sockaddr_in *)up->peername;
  379.         fsock.address = remote.in->sin_addr.s_addr;
  380.         fsock.port = remote.in->sin_port;
  381.  
  382.         /* Open the TCB in active mode */
  383.         up->cb.tcb = open_tcp(&lsock,&fsock,TCP_ACTIVE,0,
  384.          s_trcall,s_ttcall,s_tscall,0,s);
  385.  
  386.         /* Wait for the connection to complete */
  387.         while((cb.tcb = up->cb.tcb) != NULLTCB && cb.tcb->state != ESTABLISHED){
  388.             if(up->noblock){
  389.                 errno = EWOULDBLOCK;
  390.                 return -1;
  391.             } else if(pwait(up) != 0){
  392.                 errno = EINTR;
  393.                 return -1;
  394.             }
  395.         }
  396.         if(cb.tcb == NULLTCB){
  397.             /* Probably got refused */
  398.             free(up->peername);
  399.             up->peername = NULLCHAR;
  400.             errno = ECONNREFUSED;
  401.             return -1;
  402.         }
  403.         break;
  404.     case TYPE_UDP:
  405.     case TYPE_AX25UI:
  406.     case TYPE_NETROML3:
  407.     case TYPE_RAW:
  408.         /* Control block already created by bind() */
  409.         break;
  410. #ifdef    AX25
  411.     case TYPE_AX25I:
  412.         local.ax = (struct sockaddr_ax *)up->name;
  413.         remote.ax = (struct sockaddr_ax *)up->peername;
  414.         if((iface = if_lookup(remote.ax->iface)) == NULLIF){
  415.             errno = EINVAL;
  416.             return -1;
  417.         }
  418.         /* If we already have an AX25 link we can use it */
  419.         if((up->cb.ax25 = find_ax25(&remote.ax->ax25_addr)) != NULLAX25
  420.            && up->cb.ax25->state != DISCONNECTED &&
  421.            up->cb.ax25->user == -1) {
  422.             up->cb.ax25->user = s;
  423.             up->cb.ax25->r_upcall = s_arcall;
  424.             up->cb.ax25->t_upcall = s_atcall;
  425.             up->cb.ax25->s_upcall = s_ascall;
  426.             if(up->cb.ax25->state == CONNECTED
  427.                || up->cb.ax25->state == RECOVERY)
  428.                     return 0;
  429.         }
  430.         else up->cb.ax25 = open_ax25(iface,&local.ax->ax25_addr,
  431.                      &remote.ax->ax25_addr,AX_ACTIVE,
  432.                      Axwindow,s_arcall,s_atcall,s_ascall,s);
  433.  
  434.         /* Wait for the connection to complete */
  435.         while((cb.ax25 = up->cb.ax25) != NULLAX25 && cb.ax25->state != CONNECTED){
  436.             if(up->noblock){
  437.                 errno = EWOULDBLOCK;
  438.                 return -1;
  439.             } else if(pwait(up) != 0){
  440.                 errno = EINTR;
  441.                 return -1;
  442.             }
  443.         }
  444.         if(cb.ax25 == NULLAX25){
  445.             /* Connection probably already exists */
  446.             free(up->peername);
  447.             up->peername = NULLCHAR;
  448.             errno = ECONNREFUSED;
  449.             return -1;
  450.         }
  451.         break;
  452. #endif
  453. #ifdef    NETROM
  454.     case TYPE_NETROML4:
  455.         local.nr = (struct sockaddr_nr *)up->name;
  456.         remote.nr = (struct sockaddr_nr *)up->peername;
  457.         up->cb.nr4 = open_nr4(&local.nr->nr_addr,&remote.nr->nr_addr,
  458.                       AX_ACTIVE,s_nrcall,s_ntcall,s_nscall,s);
  459.  
  460.         /* Wait for the connection to complete */
  461.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB && cb.nr4->state != NR4STCON){
  462.             if(up->noblock){
  463.                 errno = EWOULDBLOCK;
  464.                 return -1;
  465.             } else if(pwait(up) != 0){
  466.                 errno = EINTR;
  467.                 return -1;
  468.             }
  469.         }
  470.         if(cb.nr4 == NULLNR4CB){
  471.             /* Connection probably already exists */
  472.             free(up->peername);
  473.             up->peername = NULLCHAR;
  474.             errno = ECONNREFUSED;
  475.             return -1;
  476.         }
  477.         break;
  478. #endif
  479.     }
  480.     return 0;
  481. }
  482. /* Wait for a connection. Valid only for connection-oriented sockets. */
  483. int
  484. accept(s,peername,peernamelen)
  485. int s;            /* Socket index */
  486. char *peername;        /* Peer name */
  487. int *peernamelen;    /* Length of peer name */
  488. {
  489.     int i;
  490.     register struct usock *up;
  491.  
  492.     if((up = itop(s)) == NULLUSOCK){
  493.         errno = EBADF;
  494.         return -1;
  495.     }
  496.     if(up->cb.p == NULLCHAR){
  497.         errno = EOPNOTSUPP;
  498.         return -1;
  499.     }
  500.     /* Accept is valid only for stream sockets */
  501.     switch(up->type){
  502.     case TYPE_TCP:
  503.     case TYPE_AX25I:
  504.     case TYPE_NETROML4:
  505.         break;
  506.     default:
  507.         errno = EOPNOTSUPP;
  508.         return -1;
  509.     }    
  510.     /* Wait for the state-change upcall routine to signal us */
  511.     while(up->cb.p != NULLCHAR && up->rdysock == -1){
  512.         if(up->noblock){
  513.             errno = EWOULDBLOCK;
  514.             return -1;
  515.         } else if(pwait(up) != 0){
  516.             errno = EINTR;
  517.             return -1;
  518.         }
  519.     }
  520.     if(up->cb.p == NULLCHAR){
  521.         /* Blown away */
  522.         errno = EBADF;
  523.         return -1;
  524.     }
  525.     i = up->rdysock;
  526.     up->rdysock = -1;
  527.  
  528.     up = &Usock[i];
  529.     if(peername != NULLCHAR && peernamelen != NULL){
  530.         *peernamelen = min(up->peernamelen,*peernamelen);
  531.         memcpy(peername,up->peername,*peernamelen);
  532.     }
  533.     return i;
  534. }
  535. /* Low-level receive routine. Passes mbuf back to user; more efficient than
  536.  * higher-level functions recv() and recvfrom(). Datagram sockets ignore
  537.  * the len parameter.
  538.  */
  539. int
  540. recv_mbuf(s,bpp,len,flags,from,fromlen)
  541. int s;            /* Socket index */
  542. struct mbuf **bpp;    /* Place to stash receive buffer */
  543. int len;        /* Maximum length to read (0 implies all) */
  544. int flags;        /* Unused; will control out-of-band data, etc */
  545. char *from;        /* Peer address (only for datagrams) */
  546. int *fromlen;        /* Length of peer address */
  547. {
  548.     register struct usock *up;
  549.     int cnt;
  550.     union cb cb;
  551.     struct socket fsocket;
  552. #ifdef    NETROM
  553.     struct nr3hdr n3hdr;
  554. #endif
  555.     union sp remote;
  556.     struct ip ip;
  557.     struct mbuf *bp;
  558.  
  559.     if((up = itop(s)) == NULLUSOCK){
  560.         errno = EBADF;
  561.         return -1;
  562.     }
  563.     switch(up->type){
  564.     case TYPE_TCP:
  565.         while((cb.tcb = up->cb.tcb) != NULLTCB
  566.          && cb.tcb->r_upcall != trdiscard
  567.                  && (cnt = recv_tcp(cb.tcb,&bp,len)) == -1){
  568.             if(up->noblock){
  569.                 errno = EWOULDBLOCK;
  570.                 return -1;
  571.             } else if(pwait(up) != 0){
  572.                 errno = EINTR;
  573.                 return -1;
  574.             }
  575.         }
  576.         if(cb.tcb == NULLTCB){
  577.             /* Connection went away */
  578.             errno = ENOTCONN;
  579.             return -1;
  580.         } else if(cb.tcb->r_upcall == trdiscard){
  581.             /* Receive shutdown has been done */
  582.             errno = ENOTCONN;    /* CHANGE */
  583.             return -1;
  584.         }
  585.         break;
  586.     case TYPE_UDP:
  587.         while((cb.udp = up->cb.udp) != NULLUDP
  588.         && (cnt = recv_udp(cb.udp,&fsocket,&bp)) == -1){
  589.             if(up->noblock){
  590.                 errno = EWOULDBLOCK;
  591.                 return -1;
  592.             } else if(pwait(up) != 0){
  593.                 errno = EINTR;
  594.                 return -1;
  595.             }
  596.         }
  597.         if(cb.udp == NULLUDP){
  598.             /* Connection went away */
  599.             errno = ENOTCONN;
  600.             return -1;
  601.         }
  602.         if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  603.             remote.in = (struct sockaddr_in *)from;
  604.             remote.in->sin_family = AF_INET;
  605.             remote.in->sin_addr.s_addr = fsocket.address;
  606.             remote.in->sin_port = fsocket.port;
  607.             *fromlen = SOCKSIZE;
  608.         }
  609.         break;
  610.     case TYPE_RAW:
  611.         while((cb.rip = up->cb.rip) != NULLRIP
  612.          && cb.rip->rcvq == NULLBUF){
  613.             if(up->noblock){
  614.                 errno = EWOULDBLOCK;
  615.                 return -1;
  616.             } else if(pwait(up) != 0){
  617.                 errno = EINTR;
  618.                 return -1;
  619.             }
  620.         }
  621.         if(cb.rip == NULLRIP){
  622.             /* Connection went away */
  623.             errno = ENOTCONN;
  624.             return -1;
  625.         }
  626.         bp = dequeue(&cb.rip->rcvq);
  627.         ntohip(&ip,&bp);
  628.         cnt = len_mbuf(bp);
  629.         if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  630.             remote.in = (struct sockaddr_in *)from;
  631.             remote.in->sin_family = AF_INET;
  632.             remote.in->sin_addr.s_addr = ip.source;
  633.             remote.in->sin_port = 0;
  634.             *fromlen = SOCKSIZE;
  635.         }
  636.         break;
  637. #ifdef    AX25
  638.     case TYPE_AX25I:
  639.         while((cb.ax25 = up->cb.ax25) != NULLAX25
  640.          && (bp = recv_ax25(cb.ax25,len)) == NULLBUF){
  641.             if(up->noblock){
  642.                 errno = EWOULDBLOCK;
  643.                 return -1;
  644.             } else if(pwait(up) != 0){
  645.                 errno = EINTR;
  646.                 return -1;
  647.             }
  648.         }
  649.         if(cb.ax25 == NULLAX25){
  650.             /* Connection went away */
  651.             errno = ENOTCONN;
  652.             return -1;
  653.         }
  654.         cnt = bp->cnt;
  655.         break;
  656.     case TYPE_AX25UI:
  657.         while(s == Axui_sock && Bcq == NULLBUF){
  658.             if(up->noblock){
  659.                 errno = EWOULDBLOCK;
  660.                 return -1;
  661.             } else if(pwait(&Bcq) != 0){
  662.                 errno = EINTR;
  663.                 return -1;
  664.             }
  665.         }
  666.         if(s != Axui_sock){
  667.             errno = ENOTCONN;
  668.             return -1;
  669.         }
  670.         bp = dequeue(&Bcq);
  671.  
  672.         if(from != NULLCHAR && fromlen != NULLINT
  673.            && *fromlen >= sizeof(struct sockaddr_ax)){
  674.             pullup(&bp,(char *)from,sizeof(struct sockaddr_ax));
  675.             *fromlen = sizeof(struct sockaddr_ax);
  676.         } else {
  677.             pullup(&bp,NULLCHAR,sizeof(struct sockaddr_ax));
  678.         }
  679.         cnt = len_mbuf(bp);
  680.         break;
  681. #endif
  682. #ifdef NETROM
  683.     case TYPE_NETROML3:
  684.         while((cb.rnr = up->cb.rnr) != NULLRNR
  685.          && cb.rnr->rcvq == NULLBUF){
  686.             if(up->noblock){
  687.                 errno = EWOULDBLOCK;
  688.                 return -1;
  689.             } else if(pwait(up) != 0){
  690.                 errno = EINTR;
  691.                 return -1;
  692.             }
  693.         }
  694.         if(cb.rnr == NULLRNR){
  695.             /* Connection went away */
  696.             errno = ENOTCONN;
  697.             return -1;
  698.         }
  699.         bp = dequeue(&cb.rnr->rcvq);
  700.         ntohnr3(&n3hdr,&bp);
  701.         cnt = len_mbuf(bp);
  702.         if(from != NULLCHAR && fromlen != NULLINT
  703.            && *fromlen >= sizeof(struct sockaddr_nr)){
  704.             remote.nr = (struct sockaddr_nr *)from;
  705.             remote.nr->nr_family = AF_NETROM;
  706.             /* The callsign of the local user is not part of
  707.                NET/ROM level 3, so that field is not used here */
  708.             memcpy(remote.nr->nr_addr.node_call,&n3hdr.source,
  709.                    AXALEN);
  710.             *fromlen = sizeof(struct sockaddr_nr);
  711.         }
  712.         break;
  713.     case TYPE_NETROML4:
  714.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB
  715.          && (bp = recv_nr4(cb.nr4,len)) == NULLBUF){
  716.             if(up->noblock){
  717.                 errno = EWOULDBLOCK;
  718.                 return -1;
  719.             } else if(pwait(up) != 0){
  720.                 errno = EINTR;
  721.                 return -1;
  722.             }
  723.         }
  724.         if(cb.nr4 == NULLNR4CB){
  725.             /* Connection went away */
  726.             errno = ENOTCONN;
  727.             return -1;
  728.         }
  729.         cnt = bp->cnt;
  730.         break;
  731. #endif
  732.     }
  733.     if(bpp != NULLBUFP)
  734.         *bpp = bp;
  735.     return cnt;
  736. }
  737. /* Low level send routine; user supplies mbuf for transmission. More
  738.  * efficient than send() or sendto(), the higher level interfaces.
  739.  * The "to" and "tolen" parameters are ignored on connection-oriented
  740.  * sockets.
  741.  *
  742.  * In case of error, bp is freed so the caller doesn't have to worry about it.
  743.  */
  744. int
  745. send_mbuf(s,bp,flags,to,tolen)
  746. int s;            /* Socket index */
  747. struct mbuf *bp;    /* Buffer to send */
  748. int flags;        /* not currently used */
  749. char *to;        /* Destination, only for datagrams */
  750. int tolen;        /* Length of destination */
  751. {
  752.     register struct usock *up;
  753.     union cb cb;
  754.     union sp local,remote;
  755.     struct socket lsock,fsock;
  756.     int cnt;
  757.  
  758.     if((up = itop(s)) == NULLUSOCK){
  759.         free_p(bp);
  760.         errno = EBADF;
  761.         return -1;
  762.     }
  763.     if(up->name == NULLCHAR){
  764.         /* Automatic local name assignment for datagram sockets */
  765.         switch(up->type){
  766.         case TYPE_UDP:
  767.         case TYPE_RAW:
  768.             autobind(s,AF_INET);
  769.             break;
  770.         case TYPE_AX25UI:
  771.             autobind(s,AF_AX25);
  772.             break;
  773.         case TYPE_NETROML3:
  774.         case TYPE_NETROML4:
  775.             autobind(s,AF_NETROM);
  776.             break;
  777.         default:
  778.             free_p(bp);
  779.             errno = ENOTCONN;
  780.             return -1;
  781.         }
  782.     }
  783.     cnt = len_mbuf(bp);
  784.     switch(up->type){
  785.     case TYPE_TCP:
  786.         if((cb.tcb = up->cb.tcb) == NULLTCB){
  787.             free_p(bp);
  788.             errno = ENOTCONN;
  789.             return -1;
  790.         }        
  791.         cnt = send_tcp(cb.tcb,bp);
  792.  
  793.         while((cb.tcb = up->cb.tcb) != NULLTCB &&
  794.          cb.tcb->sndcnt > cb.tcb->window){
  795.             /* Send queue is full */
  796.             if(up->noblock){
  797.                 errno = EWOULDBLOCK;
  798.                 return -1;
  799.             } else if(pwait(up) != 0){
  800.                 errno = EINTR;
  801.                 return -1;
  802.             }
  803.         }
  804.          if(cb.tcb == NULLTCB){
  805.             errno = ENOTCONN;
  806.             return -1;
  807.         }
  808.         break;
  809.     case TYPE_UDP:
  810.         local.in = (struct sockaddr_in *)up->name;
  811.         lsock.address = local.in->sin_addr.s_addr;
  812.         lsock.port = local.in->sin_port;
  813.         if(to != NULLCHAR)
  814.             remote.in = (struct sockaddr_in *)to;
  815.         else if(up->peername != NULLCHAR)
  816.             remote.in = (struct sockaddr_in *)up->peername;
  817.         else {
  818.             errno = ENOTCONN;
  819.             return -1;
  820.         }    
  821.         fsock.address = remote.in->sin_addr.s_addr;
  822.         fsock.port = remote.in->sin_port;
  823.         send_udp(&lsock,&fsock,0,0,bp,0,0,0);
  824.         break;
  825.     case TYPE_RAW:
  826.         local.in = (struct sockaddr_in *)up->name;
  827.         if(to != NULLCHAR)
  828.             remote.in = (struct sockaddr_in *)to;
  829.         else if(up->peername != NULLCHAR)
  830.             remote.in = (struct sockaddr_in *)up->peername;
  831.         else {
  832.             errno = ENOTCONN;
  833.             return -1;
  834.         }    
  835.         ip_send(local.in->sin_addr.s_addr,remote.in->sin_addr.s_addr,
  836.             up->cb.rip->protocol,0,0,bp,0,0,0);
  837.         break;
  838. #ifdef    AX25
  839.     case TYPE_AX25I:
  840.         if((cb.ax25 = up->cb.ax25) == NULLAX25){
  841.             free_p(bp);
  842.             errno = ENOTCONN;
  843.             return -1;
  844.         }
  845.         send_ax25(cb.ax25,bp,PID_NO_L3);
  846.  
  847.         while((cb.ax25 = up->cb.ax25) != NULLAX25 &&
  848.          len_q(cb.ax25->txq) > cb.ax25->window){
  849.             if(up->noblock){
  850.                 errno = EWOULDBLOCK;
  851.                 return -1;
  852.             } else if(pwait(up) != 0){
  853.                 errno = EINTR;
  854.                 return -1;
  855.             }
  856.         }
  857.         if(cb.ax25 == NULLAX25){
  858.             errno = EBADF;
  859.             return -1;
  860.         }
  861.         break;
  862.     case TYPE_AX25UI:
  863.         local.ax = (struct sockaddr_ax *)up->name;
  864.         if(to != NULLCHAR)
  865.             remote.ax = (struct sockaddr_ax *)to;
  866.         else if(up->peername != NULLCHAR)
  867.             remote.ax = (struct sockaddr_ax *)up->peername;
  868.         else {
  869.             errno = ENOTCONN;
  870.             return -1;
  871.         }
  872.         ax_output(if_lookup(remote.ax->iface),
  873.               (char *)&remote.ax->ax25_addr,
  874.               (char *)&local.ax->ax25_addr,PID_NO_L3,bp);
  875.         break;
  876. #endif
  877. #ifdef NETROM
  878.     case TYPE_NETROML3:
  879.         if(len_mbuf(bp) > NR4MAXINFO) {
  880.             free_p(bp);
  881.             errno = EMSGSIZE;
  882.             return -1;
  883.         }
  884.         local.nr = (struct sockaddr_nr *)up->name;
  885.         if(to != NULLCHAR)
  886.             remote.nr = (struct sockaddr_nr *)to;
  887.         else if(up->peername != NULLCHAR)
  888.             remote.nr = (struct sockaddr_nr *)up->peername;
  889.         else {
  890.             errno = ENOTCONN;
  891.             return -1;
  892.         }    
  893.         /* The NETROM username is always ignored in outgoing traffic */
  894.         nr_sendraw((struct ax25_addr *)remote.nr->nr_addr.node_call,
  895.             up->cb.rnr->protocol,up->cb.rnr->protocol,bp);
  896.         break;
  897.     case TYPE_NETROML4:
  898.         if((cb.nr4 = up->cb.nr4) == NULLNR4CB) {
  899.             free_p(bp);
  900.             errno = ENOTCONN;
  901.             return -1;
  902.         }
  903.         if(len_mbuf(bp) > NR4MAXINFO){ /* reject big packets */
  904.             free_p(bp);
  905.             errno = EMSGSIZE;
  906.             return -1;
  907.         }
  908.         send_nr4(cb.nr4,bp);
  909.  
  910.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB &&
  911.          cb.nr4->nbuffered >= cb.nr4->window){
  912.             if(up->noblock){
  913.                 errno = EWOULDBLOCK;
  914.                 return -1;
  915.             } else if(pwait(up) != 0){
  916.                 errno = EINTR;
  917.                 return -1;
  918.             }
  919.         }
  920.         if(cb.nr4 == NULLNR4CB){
  921.             errno = EBADF;
  922.             return -1;
  923.         }
  924.         break;
  925. #endif
  926.     }    
  927.     return cnt;
  928. }
  929. /* Higher-level receive routine, intended for connection-oriented sockets.
  930.  * Can be used with datagram sockets, although the sender id is lost.
  931.  */
  932. int
  933. recv(s,buf,len,flags)
  934. int s;        /* Socket index */
  935. char *buf;    /* User buffer */
  936. int len;    /* Max length to receive */
  937. int flags;    /* Unused; will eventually select oob data, etc */
  938. {
  939.     struct mbuf *bp;
  940.     int cnt;
  941.  
  942.     if(len == 0)
  943.         return 0;    /* Otherwise would be interp as "all" */
  944.  
  945.     cnt = recv_mbuf(s,&bp,len,flags,NULLCHAR,(int *)NULL);
  946.     if(cnt > 0){
  947.         cnt = min(cnt,len);
  948.         pullup(&bp,buf,cnt);
  949.         free_p(bp);
  950.     }
  951.     return cnt;
  952. }
  953. /* Higher level receive routine, intended for datagram sockets. Can also
  954.  * be used for connection-oriented sockets, although from and fromlen are
  955.  * ignored.
  956.  */
  957. int
  958. recvfrom(s,buf,len,flags,from,fromlen)
  959. int s;        /* Socket index */
  960. char *buf;    /* User buffer */
  961. int len;    /* Maximum length */
  962. int flags;    /* Unused; will eventually select oob data, etc */
  963. char *from;    /* Source address, only for datagrams */
  964. int *fromlen;    /* Length of source address */
  965. {
  966.     struct mbuf *bp;
  967.     register int cnt;
  968.  
  969.     cnt = recv_mbuf(s,&bp,len,flags,from,fromlen);
  970.     if(cnt > 0){
  971.         cnt = min(cnt,len);
  972.         pullup(&bp,buf,cnt);
  973.         free_p(bp);
  974.     }
  975.     return cnt;
  976. }
  977. /* High level send routine */
  978. int
  979. send(s,buf,len,flags)
  980. int s;        /* Socket index */
  981. char *buf;    /* User buffer */
  982. int len;    /* Length of buffer */
  983. int flags;    /* Unused; will eventually select oob data, etc */
  984. {
  985.     register struct mbuf *bp;
  986.     char sock[MAXSOCKSIZE];
  987.     int i = MAXSOCKSIZE;
  988.  
  989.     if(getpeername(s,sock,&i) == -1)
  990.         return -1;
  991.     bp = qdata(buf,len);
  992.     return send_mbuf(s,bp,flags,sock,i);
  993. }
  994. /* High level send routine, intended for datagram sockets. Can be used on
  995.  * connection-oriented sockets, but "to" and "tolen" are ignored.
  996.  */
  997. int
  998. sendto(s,buf,len,flags,to,tolen)
  999. int s;        /* Socket index */
  1000. char *buf;    /* User buffer */
  1001. int len;    /* Length of buffer */
  1002. int flags;    /* Unused; will eventually select oob data, etc */
  1003. char *to;    /* Destination, only for datagrams */
  1004. int tolen;    /* Length of destination */
  1005. {
  1006.     register struct mbuf *bp;
  1007.  
  1008.     bp = qdata(buf,len);
  1009.     return send_mbuf(s,bp,flags,to,tolen);
  1010. }
  1011. /* Return local name passed in an earlier bind() call */
  1012. int
  1013. getsockname(s,name,namelen)
  1014. int s;        /* Socket index */
  1015. char *name;    /* Place to stash name */
  1016. int *namelen;    /* Length of same */
  1017. {
  1018.     register struct usock *up;
  1019.  
  1020.     if((up = itop(s)) == NULLUSOCK){
  1021.         errno = EBADF;
  1022.         return -1;
  1023.     }
  1024.     if(name == NULLCHAR || namelen == (int *)NULL){
  1025.         errno = EFAULT;
  1026.         return -1;
  1027.     }
  1028.     if(up->name == NULLCHAR){
  1029.         /* Not bound yet */
  1030.         *namelen = 0;
  1031.         return 0;
  1032.     }
  1033.     if(up->name != NULLCHAR){
  1034.         *namelen = min(*namelen,up->namelen);
  1035.         memcpy(name,up->name,*namelen);
  1036.     }
  1037.     return 0;
  1038. }
  1039. /* Get remote name, returning result of earlier connect() call. */
  1040. int
  1041. getpeername(s,peername,peernamelen)
  1042. int s;            /* Socket index */
  1043. char *peername;        /* Place to stash name */
  1044. int *peernamelen;    /* Length of same */
  1045. {
  1046.     register struct usock *up;
  1047.  
  1048.     if((up = itop(s)) == NULLUSOCK){
  1049.         errno = EBADF;
  1050.         return -1;
  1051.     }
  1052.     if(up->peername == NULLCHAR){
  1053.         errno = ENOTCONN;
  1054.         return -1;
  1055.     }
  1056.     if(peername == NULLCHAR || peernamelen == (int *)NULL){
  1057.         errno = EFAULT;
  1058.         return -1;
  1059.     }
  1060.     *peernamelen = min(*peernamelen,up->peernamelen);
  1061.     memcpy(peername,up->peername,*peernamelen);
  1062.     return 0;
  1063. }
  1064. /* Return length of protocol queue, either send or receive. */
  1065. int
  1066. socklen(s,rtx)
  1067. int s;        /* Socket index */
  1068. int rtx;    /* 0 = receive queue, 1 = transmit queue */
  1069. {
  1070.     register struct usock *up;
  1071.  
  1072.     if((up = itop(s)) == NULLUSOCK){
  1073.         errno = EBADF;
  1074.         return -1;
  1075.     }
  1076.     if(up->cb.p == NULLCHAR){
  1077.         errno = ENOTCONN;
  1078.         return -1;
  1079.     }
  1080.     if(rtx < 0 || rtx > 1){
  1081.         errno = EINVAL;
  1082.         return -1;
  1083.     }
  1084.     switch(up->type){
  1085.     case TYPE_TCP:
  1086.         switch(rtx){
  1087.         case 0:
  1088.             return up->cb.tcb->rcvcnt;
  1089.         case 1:
  1090.             return up->cb.tcb->sndcnt;
  1091.         }
  1092.     case TYPE_UDP:
  1093.         switch(rtx){
  1094.         case 0:
  1095.             return up->cb.udp->rcvcnt;
  1096.         case 1:
  1097.             return 0;
  1098.         }
  1099. #ifdef    AX25
  1100.     case TYPE_AX25I:
  1101.         switch(rtx){
  1102.         case 0:
  1103.             return len_mbuf(up->cb.ax25->rxq);
  1104.         case 1:    /* Number of packets, not bytes */
  1105.             return len_q(up->cb.ax25->txq);
  1106.         }
  1107.     case TYPE_AX25UI:
  1108.         switch(rtx){    
  1109.         case 0:
  1110.             return len_q(Bcq);
  1111.         case 1:
  1112.             return 0;        
  1113.         }
  1114. #endif
  1115. #ifdef NETROM
  1116.     case TYPE_NETROML3:
  1117.         switch(rtx){    
  1118.         case 0:
  1119.             return len_q(up->cb.rnr->rcvq);
  1120.         case 1:
  1121.             return 0;        
  1122.         }
  1123.     case TYPE_NETROML4:
  1124.         switch(rtx){
  1125.         case 0:
  1126.             return len_mbuf(up->cb.nr4->rxq);
  1127.         case 1:    /* Number of packets, not bytes */
  1128.             return len_q(up->cb.nr4->txq);
  1129.         }
  1130. #endif
  1131.     case TYPE_RAW:
  1132.         switch(rtx){    
  1133.         case 0:
  1134.             return len_q(up->cb.rip->rcvq);
  1135.         case 1:
  1136.             return 0;        
  1137.         }
  1138.     }
  1139.     return -1;
  1140. }
  1141. /* Force retransmission. Valid only for connection-oriented sockets. */
  1142. int
  1143. sockkick(s)
  1144. int s;    /* Socket index */
  1145. {
  1146.     register struct usock *up;
  1147.  
  1148.     if((up = itop(s)) == NULLUSOCK){
  1149.         errno = EBADF;
  1150.         return -1;
  1151.     }
  1152.     if(up->cb.p == NULLCHAR){
  1153.         errno = ENOTCONN;
  1154.         return -1;
  1155.     }
  1156.     switch(up->type){
  1157.     case TYPE_TCP:
  1158.         kick_tcp(up->cb.tcb);
  1159.         break;
  1160. #ifdef    AX25
  1161.     case TYPE_AX25I:
  1162.         kick_ax25(up->cb.ax25);
  1163.         break;
  1164. #endif
  1165. #ifdef NETROM
  1166.     case TYPE_NETROML4:
  1167.         kick_nr4(up->cb.nr4);
  1168.         break;
  1169. #endif
  1170.     default:
  1171.         /* Datagram sockets can't be kicked */
  1172.         errno = EOPNOTSUPP;
  1173.         return -1;
  1174.     }
  1175.     return 0;
  1176. }
  1177.  
  1178. /* Get state of protocol. Valid only for connection-oriented sockets. */
  1179. char *
  1180. sockstate(s)
  1181. int s;        /* Socket index */
  1182. {
  1183.     register struct usock *up;
  1184.  
  1185.     if((up = itop(s)) == NULLUSOCK){
  1186.         errno = EBADF;
  1187.         return NULLCHAR;
  1188.     }
  1189.     if(up->cb.p == NULLCHAR){
  1190.         errno = ENOTCONN;
  1191.         return NULLCHAR;
  1192.     }
  1193.     switch(up->type){
  1194.     case TYPE_TCP:
  1195.         return Tcpstates[up->cb.tcb->state];
  1196. #ifdef    AX25
  1197.     case TYPE_AX25I:
  1198.         return Ax25states[up->cb.ax25->state];
  1199. #endif
  1200. #ifdef    NETROM
  1201.     case TYPE_NETROML4:
  1202.         return Nr4states[up->cb.nr4->state];
  1203. #endif
  1204.     default:
  1205.         /* Datagram sockets don't have state */
  1206.         errno = EOPNOTSUPP;
  1207.         return NULLCHAR;
  1208.     }
  1209.     /*NOTREACHED*/
  1210. }
  1211. /* Change owner of socket, return previous owner */
  1212. struct proc *
  1213. sockowner(s,newowner)
  1214. int s;            /* Socket index */
  1215. struct proc *newowner;    /* Process table address of new owner */
  1216. {
  1217.     register struct usock *up;
  1218.     struct proc *pp;
  1219.  
  1220.     if((up = itop(s)) == NULLUSOCK){
  1221.         errno = EBADF;
  1222.         return NULLPROC;
  1223.     }
  1224.     pp = up->owner;
  1225.     if(newowner != NULLPROC)
  1226.         up->owner = newowner;
  1227.     return pp;
  1228. }
  1229. /* Close down a socket three ways. Type 0 means "no more receives"; this
  1230.  * replaces the incoming data upcall with a routine that discards further
  1231.  * data. Type 1 means "no more sends", and obviously corresponds to sending
  1232.  * a TCP FIN. Type 2 means "no more receives or sends". This I interpret
  1233.  * as "abort the connection".
  1234.  */
  1235. int
  1236. shutdown(s,how)
  1237. int s;        /* Socket index */
  1238. int how;    /* (see above) */
  1239. {
  1240.     register struct usock *up;
  1241.  
  1242.     if((up = itop(s)) == NULLUSOCK){
  1243.         errno = EBADF;
  1244.         return -1;
  1245.     }
  1246.     if(up->cb.p == NULLCHAR){
  1247.         errno = ENOTCONN;
  1248.         return -1;
  1249.     }
  1250.     switch(up->type){
  1251.     case TYPE_TCP:
  1252.         switch(how){
  1253.         case 0:    /* No more receives -- replace upcall */
  1254.             up->cb.tcb->r_upcall = trdiscard;
  1255.             break;
  1256.         case 1:    /* Send EOF */
  1257.             close_tcp(up->cb.tcb);
  1258.             break;
  1259.         case 2:    /* Blow away TCB */
  1260.             reset_tcp(up->cb.tcb);
  1261.             up->cb.tcb = NULLTCB;
  1262.             break;
  1263.         }
  1264.         break;
  1265. #ifdef    AX25
  1266.     case TYPE_AX25UI:
  1267.         close_s(s);
  1268.         break;
  1269.     case TYPE_AX25I:
  1270.         switch(how){
  1271.         case 0:
  1272.         case 1:    /* Attempt regular disconnect */
  1273.             disc_ax25(up->cb.ax25);
  1274.             break;
  1275.         case 2: /* Blow it away */
  1276.             reset_ax25(up->cb.ax25);
  1277.             up->cb.ax25 = NULLAX25;
  1278.             break;
  1279.         }
  1280.         break;        
  1281. #endif
  1282. #ifdef    NETROM
  1283.     case TYPE_NETROML3:
  1284.         close_s(s);
  1285.         break;
  1286.     case TYPE_NETROML4:
  1287.         switch(how){
  1288.         case 0:
  1289.         case 1:    /* Attempt regular disconnect */
  1290.             disc_nr4(up->cb.nr4);
  1291.             break;
  1292.         case 2: /* Blow it away */
  1293.             reset_nr4(up->cb.nr4);
  1294.             up->cb.nr4 = NULLNR4CB;
  1295.             break;
  1296.         }
  1297.         break;        
  1298. #endif
  1299.     case TYPE_RAW:
  1300.         close_s(s);
  1301.         break;
  1302.     default:
  1303.         errno = EOPNOTSUPP;
  1304.         return -1;
  1305.     }
  1306.     psignal(up,0);
  1307.     return 0;
  1308. }
  1309. /* Close a socket, freeing it for reuse. Try to do a graceful close on a
  1310.  * TCP socket, if possible
  1311.  */
  1312. int
  1313. close_s(s)
  1314. int s;        /* Socket index */
  1315. {
  1316.     register struct usock *up;
  1317.  
  1318.     if((up = itop(s)) == NULLUSOCK){
  1319.         errno = EBADF;
  1320.         return -1;
  1321.     }
  1322.     switch(up->type){
  1323.     case TYPE_TCP:
  1324.         if(up->cb.tcb != NULLTCB){    /* In case it's been reset */
  1325.             up->cb.tcb->r_upcall = trdiscard;
  1326.             /* Tell the CLOSED upcall there's no more socket */
  1327.             up->cb.tcb->user = -1;
  1328.             close_tcp(up->cb.tcb);
  1329.         }
  1330.         break;
  1331.     case TYPE_UDP:
  1332.         if(up->cb.udp != NULLUDP){
  1333.             del_udp(up->cb.udp);
  1334.         }
  1335.         break;
  1336. #ifdef    AX25
  1337.     case TYPE_AX25I:
  1338.         if(up->cb.ax25 != NULLAX25){
  1339.             /* Tell the CLOSED upcall there's no more socket */
  1340.             up->cb.ax25->user = -1;
  1341.             disc_ax25(up->cb.ax25);
  1342.         }
  1343.         break;
  1344.     case TYPE_AX25UI:
  1345.         Axui_sock = -1;
  1346.         free_q(&Bcq);
  1347.         psignal(&Bcq,0);    /* Unblock any reads */
  1348.         break;
  1349. #endif
  1350. #ifdef    NETROM
  1351.     case TYPE_NETROML3:
  1352.         del_rnr(up->cb.rnr);
  1353.         break;
  1354.     case TYPE_NETROML4:
  1355.         if(up->cb.nr4 != NULLNR4CB){
  1356.             /* Tell the CLOSED upcall there's no more socket */
  1357.             up->cb.nr4->user = -1;
  1358.             disc_nr4(up->cb.nr4);
  1359.         }
  1360.         break;
  1361. #endif
  1362.     case TYPE_RAW:
  1363.         del_ip(up->cb.rip);
  1364.         break;
  1365.     default:
  1366.         errno = EOPNOTSUPP;
  1367.         return -1;
  1368.     }
  1369.     free(up->name);
  1370.     free(up->peername);
  1371.  
  1372.     up->cb.p = NULLCHAR;
  1373.     up->name = up->peername = NULLCHAR;
  1374.     up->type = NOTUSED;
  1375.     psignal(up,0);    /* Wake up anybody doing an accept() or recv() */
  1376.     return 0;
  1377. }
  1378. /* Return ASCII string giving reason for connection closing */
  1379. char *
  1380. sockerr(s)
  1381. int s;    /* Socket index */
  1382. {
  1383.     register struct usock *up;
  1384.  
  1385.     if((up = itop(s)) == NULLUSOCK){
  1386.         errno = EBADF;
  1387.         return Badsocket;
  1388.     }
  1389.     switch(up->type){
  1390. #ifdef    AX25
  1391.     case TYPE_AX25I:
  1392.         if(up->cb.ax25 != NULLAX25)
  1393.             return NULLCHAR;    /* nothing wrong */
  1394.         return Axreasons[up->errcodes[0]];
  1395. #endif
  1396. #ifdef    NETROM
  1397.     case TYPE_NETROML4:
  1398.         if(up->cb.nr4 != NULLNR4CB)
  1399.             return NULLCHAR;    /* nothing wrong */
  1400.         return Nr4reasons[up->errcodes[0]];
  1401. #endif
  1402.     case TYPE_TCP:
  1403.         if(up->cb.tcb != NULLTCB)
  1404.             return NULLCHAR;    /* nothing wrong */        
  1405.         return Tcpreasons[up->errcodes[0]];
  1406.     default:
  1407.         errno = EOPNOTSUPP;    /* not yet, anyway */
  1408.         return NULLCHAR;
  1409.     }
  1410. }
  1411. /* End of user socket primitives, begin user utility subroutines */
  1412.  
  1413. /* Receive a newline-terminated line from a socket, returning # chars read */
  1414. int
  1415. recvline(s,buf,len)
  1416. int s;        /* Socket index */
  1417. char *buf;    /* User buffer */
  1418. unsigned len;    /* Length of buffer */
  1419. {
  1420.     char c;
  1421.     int cnt = 0;
  1422.     struct usock *up;
  1423.  
  1424.     up = itop(s);
  1425.     while(len-- > 1){
  1426.         if(recv(s,&c,1,0) != 1){
  1427.             cnt = -1;
  1428.             break;
  1429.         }
  1430.         if((up->type == TYPE_AX25I || up->type == TYPE_NETROML4)
  1431.            && uchar(c) == '\r')
  1432.             c = '\n';
  1433.         *buf++ = c;
  1434.         cnt++;
  1435.         if(uchar(c) == '\n')
  1436.             break;
  1437.     }
  1438.     *buf = '\0';
  1439.     return cnt;
  1440. }
  1441. /* Do printf on a user socket */
  1442. #if    defined(ANSIPROTO) && !defined(AMIGA)
  1443. int
  1444. usprintf(int s,char *fmt,...)
  1445. {
  1446.     register struct mbuf *bp;
  1447.     int len;
  1448.     va_list args;
  1449.  
  1450.     va_start(args,fmt);
  1451.     bp = alloc_mbuf(200);
  1452.     len = vsprintf(bp->data,fmt,args);
  1453.     bp->cnt = strlen(bp->data);
  1454.     send_mbuf(s,bp,0,NULLCHAR,0);
  1455.     va_end(args);
  1456.     return len;
  1457. }
  1458. #else
  1459. /*VARARGS*/
  1460. int
  1461. usprintf(s,fmt,arg1,arg2,arg3,arg4,arg5,arg6)
  1462. int s;            /* Socket index */
  1463. char *fmt;        /* Message format */
  1464. int arg1,arg2,arg3;    /* Arguments */
  1465. int arg4,arg5,arg6;
  1466. {
  1467.     register struct mbuf *bp;
  1468.     int len;
  1469.  
  1470.     bp = alloc_mbuf(200);
  1471.     len = sprintf(bp->data,fmt,arg1,arg2,arg3,arg4,arg5,arg6);
  1472.     bp->cnt = strlen(bp->data);
  1473.     send_mbuf(s,bp,0,NULLCHAR,0);
  1474.     return len;
  1475. }
  1476. #endif
  1477. /* Convert a socket (address + port) to an ascii string of the form
  1478.  * aaa.aaa.aaa.aaa:ppppp
  1479.  */
  1480. char *
  1481. psocket(p)
  1482. void *p;    /* Pointer to structure to decode */
  1483. {
  1484. #if    defined(AX25) || defined(NETROM)
  1485.     char tmp[11];
  1486. #endif
  1487.     static char buf[30];
  1488.     union sp sp;
  1489.     struct socket socket;
  1490.  
  1491.     sp.p = p;
  1492.     switch(sp.sa->sa_family){
  1493.     case AF_INET:
  1494.         socket.address = sp.in->sin_addr.s_addr;
  1495.         socket.port = sp.in->sin_port;
  1496.         strcpy(buf,pinet(&socket));
  1497.         break;
  1498. #ifdef    AX25
  1499.     case AF_AX25:
  1500.         pax25(tmp,&sp.ax->ax25_addr);
  1501.         sprintf(buf,"%s on %s",tmp,sp.ax->iface);
  1502.         break;
  1503. #endif
  1504. #ifdef    NETROM
  1505.     case AF_NETROM:
  1506.         pax25(tmp,(struct ax25_addr *)sp.nr->nr_addr.user_call);
  1507.         sprintf(buf,"%s @ ",tmp);
  1508.         pax25(tmp,(struct ax25_addr *)sp.nr->nr_addr.node_call);
  1509.         strcat(buf,tmp);
  1510.         break;
  1511. #endif
  1512.     }
  1513.     return buf;
  1514. }
  1515. /* Read a character from a socket with stream buffering */
  1516. int
  1517. recvchar(s,bpp)
  1518. int s;            /* Socket index */
  1519. struct mbuf **bpp;    /* User-supplied buffer pointer */
  1520. {
  1521.     char c;
  1522.  
  1523.     if(*bpp == NULLBUF)
  1524.         recv_mbuf(s,bpp,0,0,NULLCHAR,0);    /* Replenish */
  1525.  
  1526.     if(pullup(bpp,&c,1) != 1)
  1527.         return -1;
  1528.     return uchar(c);
  1529. }
  1530. /* Blow away all sockets belonging to a certain process. Used by killproc(). */
  1531. void
  1532. freesock(pp)
  1533. struct proc *pp;
  1534. {
  1535.     register struct usock *up;
  1536.     register int i;
  1537.  
  1538.     for(i=0;i < Nusock;i++){
  1539.         up = &Usock[i];
  1540.         if(up->type != NOTUSED && up->owner == pp)
  1541.             shutdown(i,2);
  1542.     }
  1543. }
  1544.  
  1545. /* End of user utility subroutines, start internal subroutines */
  1546.  
  1547. /* Raw IP receive upcall routine */
  1548. void
  1549. rip_recv(rp)
  1550. struct raw_ip *rp;
  1551. {
  1552.     psignal(itop(rp->user),1);
  1553.     pwait(NULL);
  1554. }
  1555.  
  1556. /* UDP receive upcall routine */
  1557. static void
  1558. s_urcall(iface,udp,cnt)
  1559. struct iface *iface;
  1560. struct udp_cb *udp;
  1561. int cnt;
  1562. {
  1563.     psignal(itop(udp->user),1);
  1564.     pwait(NULL);
  1565. }
  1566. /* TCP receive upcall routine */
  1567. static void
  1568. s_trcall(tcb,cnt)
  1569. struct tcb *tcb;
  1570. int cnt;
  1571. {
  1572.     /* Wake up anybody waiting for data, and let them run */
  1573.     psignal(itop(tcb->user),1);
  1574.     pwait(NULL);
  1575. }
  1576. /* TCP transmit upcall routine */
  1577. static void
  1578. s_ttcall(tcb,cnt)
  1579. struct tcb *tcb;
  1580. int cnt;
  1581. {
  1582.     /* Wake up anybody waiting to send data, and let them run */
  1583.     psignal(itop(tcb->user),1);
  1584.     pwait(NULL);
  1585. }
  1586. /* TCP state change upcall routine */
  1587. static void
  1588. s_tscall(tcb,old,new)
  1589. struct tcb *tcb;
  1590. int old,new;
  1591. {
  1592.     int s,ns;
  1593.     struct usock *up,*nup,*oup;
  1594.     union sp sp;
  1595.  
  1596.     s = tcb->user;
  1597.     oup = up = itop(s);
  1598.  
  1599.     switch(new){
  1600.     case CLOSED:
  1601.         /* Clean up. If the user has already closed the socket,
  1602.          * then up will be null (s was set to -1 by the close routine).
  1603.          * If not, then this is an abnormal close (e.g., a reset)
  1604.          * and clearing out the pointer in the socket structure will
  1605.          * prevent any further operations on what will be a freed
  1606.          * control block. Also wake up anybody waiting on events
  1607.          * related to this tcb so they will notice it disappearing.
  1608.          */
  1609.         if(up != NULLUSOCK){
  1610.             up->cb.tcb = NULLTCB;
  1611.             up->errcodes[0] = tcb->reason;
  1612.             up->errcodes[1] = tcb->type;
  1613.             up->errcodes[2] = tcb->code;
  1614.         }
  1615.         del_tcp(tcb);
  1616.         break;
  1617.     case SYN_RECEIVED:
  1618.         /* Handle an incoming connection. If this is a server TCB,
  1619.          * then we're being handed a "clone" TCB and we need to
  1620.          * create a new socket structure for it. In either case,
  1621.          * find out who we're talking to and wake up the guy waiting
  1622.          * for the connection.
  1623.          */
  1624.         if(tcb->flags.clone){
  1625.             /* Clone the socket */
  1626.             ns = socket(AF_INET,SOCK_STREAM,0);
  1627.             nup = &Usock[ns];
  1628.             ASSIGN(*nup,*up);
  1629.             tcb->user = ns;
  1630.             nup->cb.tcb = tcb;
  1631.             /* Allocate new memory for the name areas */
  1632.             nup->name = malloc(SOCKSIZE);
  1633.             nup->peername = malloc(SOCKSIZE);
  1634.             /* Store the new socket # in the old one */
  1635.             up->rdysock = ns;
  1636.             up = nup;
  1637.             s = ns;
  1638.         } else {
  1639.             /* Allocate space for the peer's name */
  1640.             up->peername = malloc(SOCKSIZE);
  1641.             /* Store the old socket # in the old socket */
  1642.             up->rdysock = s;
  1643.         }
  1644.         /* Load the addresses. Memory for the name has already
  1645.          * been allocated, either above or in the original bind.
  1646.          */
  1647.         sp.p = up->name;
  1648.         sp.in->sin_family = AF_INET;
  1649.         sp.in->sin_addr.s_addr = up->cb.tcb->conn.local.address;
  1650.         sp.in->sin_port = up->cb.tcb->conn.local.port;
  1651.         up->namelen = SOCKSIZE;
  1652.  
  1653.         sp.p = up->peername;
  1654.         sp.in->sin_family = AF_INET;
  1655.         sp.in->sin_addr.s_addr = up->cb.tcb->conn.remote.address;
  1656.         sp.in->sin_port = up->cb.tcb->conn.remote.port;
  1657.         up->peernamelen = SOCKSIZE;
  1658.  
  1659.         /* Wake up the guy accepting it, and let him run */
  1660.         psignal(oup,1);
  1661.         pwait(NULL);
  1662.         break;
  1663.     default:    /* Ignore all other state transitions */
  1664.         break;
  1665.     }
  1666.     psignal(up,0);    /* In case anybody's waiting */
  1667. }
  1668. /* Discard data received on a TCP connection. Used after a receive shutdown or
  1669.  * close_s until the TCB disappears.
  1670.  */
  1671. static void
  1672. trdiscard(tcb,cnt)
  1673. struct tcb *tcb;
  1674. int cnt;
  1675. {
  1676.     struct mbuf *bp;
  1677.  
  1678.     recv_tcp(tcb,&bp,cnt);
  1679.     free_p(bp);
  1680. }
  1681. #ifdef    AX25
  1682. /* AX.25 receive upcall */
  1683. void
  1684. s_arcall(axp,cnt)
  1685. struct ax25_cb *axp;
  1686. int cnt;
  1687. {
  1688.     int ns;
  1689.     struct usock *up,*nup,*oup;
  1690.     union sp sp;
  1691.  
  1692.     up = itop(axp->user);
  1693.     /* When AX.25 data arrives for the first time the AX.25 listener
  1694.        is notified, if active. If the AX.25 listener is a server its
  1695.        socket is duplicated in the same manner as in s_tscall().
  1696.      */
  1697.     if (Axi_sock != -1 && axp->user == -1) {
  1698.         oup = up = itop(Axi_sock);
  1699.         /* From now on, use the same upcalls as the listener */
  1700.         axp->t_upcall = up->cb.ax25->t_upcall;
  1701.         axp->r_upcall = up->cb.ax25->r_upcall;
  1702.         axp->s_upcall = up->cb.ax25->s_upcall;
  1703.         if (up->cb.ax25->flags.clone) {
  1704.             /* Clone the socket */
  1705.             ns = socket(AF_AX25,SOCK_STREAM,0);
  1706.             nup = &Usock[ns];
  1707.             ASSIGN(*nup,*up);
  1708.             axp->user = ns;
  1709.             nup->cb.ax25 = axp;
  1710.             /* Allocate new memory for the name areas */
  1711.             nup->name = malloc(sizeof(struct sockaddr_ax));
  1712.             nup->peername = malloc(sizeof(struct sockaddr_ax));
  1713.             /* Store the new socket # in the old one */
  1714.             up->rdysock = ns;
  1715.             up = nup;
  1716.         } else {
  1717.             axp->user = Axi_sock;
  1718.             del_ax25(up->cb.ax25);
  1719.             up->cb.ax25 = axp;
  1720.             /* Allocate space for the peer's name */
  1721.             up->peername = malloc(sizeof(struct sockaddr_ax));
  1722.             /* Store the old socket # in the old socket */
  1723.             up->rdysock = Axi_sock;
  1724.         }
  1725.         /* Load the addresses. Memory for the name has already
  1726.          * been allocated, either above or in the original bind.
  1727.          */
  1728.         sp.p = up->name;
  1729.         sp.ax->sax_family = AF_AX25;
  1730.         ASSIGN(sp.ax->ax25_addr,axp->local);
  1731.         memcpy(sp.ax->iface,axp->iface->name,ILEN);
  1732.         up->namelen = sizeof(struct sockaddr_ax);
  1733.  
  1734.         sp.p = up->peername;
  1735.         sp.ax->sax_family = AF_AX25;
  1736.         ASSIGN(sp.ax->ax25_addr,axp->remote);
  1737.         memcpy(sp.ax->iface,axp->iface->name,ILEN);
  1738.         up->peernamelen = sizeof(struct sockaddr_ax);
  1739.         /* Wake up the guy accepting it, and let him run */
  1740.         psignal(oup,1);
  1741.         pwait(NULL);
  1742.         return;
  1743.     }
  1744.     /* Wake up anyone waiting, and let them run */
  1745.     psignal(up,1);
  1746.     pwait(NULL);
  1747. }
  1748. /* AX.25 transmit upcall */
  1749. void
  1750. s_atcall(axp,cnt)
  1751. struct ax25_cb *axp;
  1752. int cnt;
  1753. {
  1754.     /* Wake up anyone waiting, and let them run */
  1755.     psignal(itop(axp->user),1);
  1756.     pwait(NULL);
  1757. }
  1758. /* AX25 state change upcall routine */
  1759. void
  1760. s_ascall(axp,old,new)
  1761. register struct ax25_cb *axp;
  1762. int old,new;
  1763. {
  1764.     int s;
  1765.     struct usock *up;
  1766.  
  1767.     s = axp->user;
  1768.     up = itop(s);
  1769.  
  1770.     switch(new){
  1771.     case DISCONNECTED:
  1772.         /* Clean up. If the user has already closed the socket,
  1773.          * then up will be null (s was set to -1 by the close routine).
  1774.          * If not, then this is an abnormal close (e.g., a reset)
  1775.          * and clearing out the pointer in the socket structure will
  1776.          * prevent any further operations on what will be a freed
  1777.          * control block. Also wake up anybody waiting on events
  1778.          * related to this block so they will notice it disappearing.
  1779.          */
  1780.         if(up != NULLUSOCK){
  1781.             up->errcodes[0] = axp->reason;
  1782.             up->cb.ax25 = NULLAX25;
  1783.         }
  1784.         del_ax25(axp);
  1785.         break;
  1786.     default:    /* Other transitions are ignored */
  1787.         break;
  1788.     }
  1789.     psignal(up,0);    /* In case anybody's waiting */
  1790. }
  1791. #endif
  1792. #ifdef NETROM
  1793. /* NET/ROM receive upcall routine */
  1794. static void
  1795. s_nrcall(cb,cnt)
  1796. struct nr4cb *cb;
  1797. int cnt;
  1798. {
  1799.     /* Wake up anybody waiting for data, and let them run */
  1800.     psignal(itop(cb->user),1);
  1801.     pwait(NULL);
  1802. }
  1803. /* NET/ROM transmit upcall routine */
  1804. static void
  1805. s_ntcall(cb,cnt)
  1806. struct nr4cb *cb;
  1807. int cnt;
  1808. {
  1809.     /* Wake up anybody waiting to send data, and let them run */
  1810.     psignal(itop(cb->user),1);
  1811.     pwait(NULL);
  1812. }
  1813. /* NET/ROM state change upcall routine */
  1814. static void
  1815. s_nscall(cb,old,new)
  1816. struct nr4cb *cb;
  1817. int old,new;
  1818. {
  1819.     int s,ns;
  1820.     struct usock *up,*nup,*oup;
  1821.     union sp sp;
  1822.  
  1823.     s = cb->user;
  1824.     oup = up = itop(s);
  1825.  
  1826.      if(new == NR4STDISC && up != NULLUSOCK){
  1827.         /* Clean up. If the user has already closed the socket,
  1828.          * then up will be null (s was set to -1 by the close routine).
  1829.          * If not, then this is an abnormal close (e.g., a reset)
  1830.          * and clearing out the pointer in the socket structure will
  1831.          * prevent any further operations on what will be a freed
  1832.          * control block. Also wake up anybody waiting on events
  1833.          * related to this cb so they will notice it disappearing.
  1834.          */
  1835.          up->cb.nr4 = NULLNR4CB;
  1836.          up->errcodes[0] = cb->dreason;
  1837.      }
  1838.      if(new == NR4STCON && old == NR4STDISC){
  1839.         /* Handle an incoming connection. If this is a server cb,
  1840.          * then we're being handed a "clone" cb and we need to
  1841.          * create a new socket structure for it. In either case,
  1842.          * find out who we're talking to and wake up the guy waiting
  1843.          * for the connection.
  1844.          */
  1845.         if(cb->clone){
  1846.             /* Clone the socket */
  1847.             ns = socket(AF_NETROM,SOCK_SEQPACKET,0);
  1848.             nup = &Usock[ns];
  1849.             ASSIGN(*nup,*up);
  1850.             cb->user = ns;
  1851.             nup->cb.nr4 = cb;
  1852.             cb->clone = 0; /* to avoid getting here again */
  1853.             /* Allocate new memory for the name areas */
  1854.             nup->name = malloc(sizeof(struct sockaddr_nr));
  1855.             nup->peername = malloc(sizeof(struct sockaddr_nr));
  1856.             /* Store the new socket # in the old one */
  1857.             up->rdysock = ns;
  1858.             up = nup;
  1859.             s = ns;
  1860.         } else {
  1861.             /* Allocate space for the peer's name */
  1862.             up->peername = malloc(sizeof(struct sockaddr_nr));
  1863.             /* Store the old socket # in the old socket */
  1864.             up->rdysock = s;
  1865.         }
  1866.         /* Load the addresses. Memory for the name has already
  1867.          * been allocated, either above or in the original bind.
  1868.          */
  1869.         sp.p = up->name;
  1870.         sp.nr->nr_family = AF_NETROM;
  1871.         ASSIGN(sp.nr->nr_addr,up->cb.nr4->local);
  1872.         up->namelen = sizeof(struct sockaddr_nr);
  1873.  
  1874.         sp.p = up->peername;
  1875.         sp.nr->nr_family = AF_NETROM;
  1876.         ASSIGN(sp.nr->nr_addr,up->cb.nr4->remote);
  1877.         up->peernamelen = sizeof(struct sockaddr_nr);
  1878.  
  1879.         /* Wake up the guy accepting it, and let him run */
  1880.         psignal(oup,1);
  1881.         pwait(NULL);
  1882.     }
  1883.      /* Ignore all other state transitions */    
  1884.     psignal(up,0);    /* In case anybody's waiting */
  1885. }
  1886. #endif
  1887.  
  1888. /* Verify address family and length according to the socket type */
  1889. static int
  1890. checkaddr(type,name,namelen)
  1891. int type;
  1892. char *name;
  1893. int namelen;
  1894. {
  1895.     register struct sockaddr *sp;
  1896.  
  1897.     sp = (struct sockaddr *)name;
  1898.     /* Verify length and address family according to protocol */
  1899.     switch(type){
  1900.     case TYPE_TCP:
  1901.     case TYPE_UDP:
  1902.         if(sp->sa_family != AF_INET
  1903.          || namelen != sizeof(struct sockaddr_in))
  1904.             return -1;
  1905.         break;
  1906.     case TYPE_AX25I:
  1907.     case TYPE_AX25UI:
  1908.         if(sp->sa_family != AF_AX25
  1909.          || namelen != sizeof(struct sockaddr_ax))
  1910.             return -1;
  1911.         break;
  1912.     case TYPE_NETROML3:
  1913.     case TYPE_NETROML4:
  1914.         if(sp->sa_family != AF_NETROM
  1915.          || namelen != sizeof(struct sockaddr_nr))
  1916.             return -1;
  1917.         break;
  1918.     }
  1919.     return 0;
  1920. }
  1921. /* Convert a socket index to an internal user socket structure pointer */
  1922. static struct usock *
  1923. itop(s)
  1924. register int s;    /* Socket index */
  1925. {
  1926.     register struct usock *up;
  1927.  
  1928.     if(s < 0 || s >= Nusock)
  1929.         return NULLUSOCK;
  1930.  
  1931.     up = &Usock[s];
  1932.  
  1933.     if(up->type == NOTUSED)
  1934.         return NULLUSOCK;
  1935.     return up;
  1936. }
  1937. /* Issue an automatic bind of a local address */
  1938. static void
  1939. autobind(s,af)
  1940. int s,af;
  1941. {
  1942.     char buf[MAXSOCKSIZE];
  1943.     union sp sp;
  1944.  
  1945.     sp.p = buf;
  1946.     switch(af){
  1947.     case AF_INET:
  1948.         sp.in->sin_family = AF_INET;
  1949.         sp.in->sin_addr.s_addr = Ip_addr;
  1950.         sp.in->sin_port = Lport++;
  1951.         bind(s,sp.p,sizeof(struct sockaddr_in));
  1952.         break;
  1953. #ifdef    AX25
  1954.     case AF_AX25:
  1955.         sp.ax->sax_family = AF_AX25;
  1956.         memcpy(sp.ax->ax25_addr.call,Mycall.call,ALEN);
  1957.         sp.ax->ax25_addr.ssid = Mycall.ssid;
  1958.         bind(s,sp.p,sizeof(struct sockaddr_ax));
  1959.         break;
  1960. #endif
  1961. #ifdef    NETROM
  1962.     case AF_NETROM:
  1963.         sp.nr->nr_family = AF_NETROM;
  1964.         memcpy(sp.nr->nr_addr.user_call,&Mycall,AXALEN);
  1965.         memcpy(sp.nr->nr_addr.node_call,&Mycall,AXALEN);
  1966.         bind(s,sp.p,sizeof(struct sockaddr_nr));
  1967.         break;
  1968. #endif
  1969.     }
  1970. }
  1971.  
  1972.